#include "Map.h"

Map::Map()
	:mpSprites(nullptr)
	,mpTiles(nullptr) //initializer list
	,mNumSprites(0)
	, mTileSize(0)
	, mColumns(0)
	,mRows(0)
{
}


Map::~Map()
{
}


void Map::Load(const char* pLevel, const char* pTexturePack)
{
	Unload();

	if (!LoadLevel(pLevel))
	{
		Unload();
		return;
	}

	if (!LoadTexturePack(pTexturePack))
	{
		Unload();
		return;
	}

}

void Map::Unload()
{

	for (int i=0; i<mNumSprites; ++i)
	{
		mpSprites[i].Unload();
	}

	//deleting memory
	//removing key from lock when leaving house
	delete[] mpSprites;
	mpSprites = nullptr;

	delete[] mpTiles;
	mpTiles = nullptr;

	mNumSprites=0;
	mTileSize=0;
	mColumns=0;
	mRows=0;

}

void Map::Update(float deltaTime)
{
}

void Map::Render(const SVector2& viewOffset)
{
	for (int y=0; y< mRows; ++y)
	{
		for (int x = 0; x< mColumns; ++x)
		{
			const int index = GetIndex(x, y);
			SVector2 pos((float)x*mTileSize, (float)y*mTileSize);
			SVector2 renderPosition = pos - viewOffset;
			mpSprites[mpTiles[index]].SetPosition(renderPosition);
			mpSprites[mpTiles[index]].Render();
		}
	}
}

bool Map::TestCollision(const SLineSegment& segment, SRect& rect) const
{
	if (segment.from.x < 0.0f || segment.from.x >= GetWidth() || 
		segment.from.y < 0.0f || segment.from.y >= GetHeight() ||
		segment.to.x < 0.0f || segment.to.x >= GetWidth() || 
		segment.to.y < 0.0f || segment.to.y >= GetHeight() )
	{
		return false;
	}

	const int minX= (int)(segment.from.x / mTileSize);
	const int minY= (int)(segment.from.y / mTileSize);
	const int maxX= (int)(segment.to.x / mTileSize);
	const int maxY= (int)(segment.to.y / mTileSize);

	rect = SRect();

	bool collision = false;
	for (int y= minY; y <= maxY; ++y)
	{
		for (int x= minX; x <= maxX; ++x)
		{
			if (IsBlocked(x,y))
			{
				rect += GetBoundingBox (x,y);
				collision = true;

			}
		}
	}

	return collision;
}

bool Map::LoadLevel(const char* pLevel)
{
	FILE* pFile = nullptr;

	//c file opening
	fopen_s(&pFile,pLevel,"r");

	if (pFile == nullptr)
	{
		return false;
	}

	//file reading
	//the * before s descards the string from the file you output
	fscanf_s(pFile,"%*s %d", &mTileSize);
	fscanf_s(pFile,"%*s %d", &mColumns);
	fscanf_s(pFile,"%*s %d", &mRows);

	mpTiles= new int[mColumns * mRows];

	fgetc(pFile); //endline character to move to newline 

	for (int y=0; y< mRows; ++y)
	{
		for (int x = 0; x< mColumns; ++x)
		{
			const int index = GetIndex(x, y);
			mpTiles[index] = fgetc(pFile) - '0';
		}
		fgetc(pFile);
	}

	fclose(pFile);
	return true;
}

bool  Map::LoadTexturePack(const char * pTexturePack)
{
	FILE* pFile = nullptr;
	//c file opening
	fopen_s(&pFile,pTexturePack,"r");

	if (pFile == nullptr)
	{
		return false;
	}

	//file reading
	//the * before s descards the string from the file you output
	fscanf(pFile,"%*s %d", &mNumSprites);

	mpSprites= new SGE_Sprite[mNumSprites];

	char buffer[256];
	for (int i=0; i<mNumSprites; ++i)
	{
		fscanf_s(pFile,"%s", buffer, 256);
		mpSprites[i].Load(buffer);
	}

	fclose(pFile);
	return true;
}

int Map::GetIndex(int x, int y) const
{
	return x + (y * mColumns);
	// 3d array is z+(ymColumns*mRows)
}

bool Map::IsBlocked (int x, int y) const
{
	const int index = GetIndex(x,y);
	int type = mpTiles[index];
	return (type > 1); //HACK assumes > 1 means not walkable (instead of if statement)
}

SRect Map::GetBoundingBox(int x, int y) const
{
	SRect boundingBox;
	boundingBox.min.x =(float) x * mTileSize;
	boundingBox.min.y =(float) y * mTileSize; 
	boundingBox.max.x =(float) ((x + 1) * mTileSize) - 1;
	boundingBox.max.y =(float) ((y + 1) * mTileSize) - 1;
	return boundingBox;
}
